import os
import re
import csv
import pandas as pd
from docx import Document

#定义函数来完成我的功能，结尾只要调用就可以实现关键功能
#需要参数为：字符串类型的sql建表语句和输出目录
def export_table_info(table_create_sql, csv_file='./',flag=0):
    print(table_create_sql)
    #删除建表语句的所有换行符
    match=re.sub('\n','',table_create_sql)
    #将所有连续的空格符替换为单个换行符
    match=re.sub('[ ]+',' ',match)
    print('sql:',match)
    t_name=re.search('.*comment \'(.*)\';',match).group(1)+'：'
    print('t_name:',t_name)
    print()
    csv_file+=re.search('create table ([a-zA-Z0-9_.]+)\(',match).group(1)+'.csv'
    print(csv_file)
    #删除掉create table ***的开头语句和第一个正括号，只为保留关键内容
    match=re.sub('.*?\(','',match,count=1)
    #删除掉最后一个反括号和分号，只为保留关键内容
    match=re.sub('\) comment .*;','',match)
    match=re.sub('\)[ ;]+\0','\0',match)
    match=re.sub('[Kk][Ee][Yy]\(','key (',match)
    match=re.sub('\( ','(',match)
    match=re.sub('\)[ ]+? ',') ',match)
    print("match: ", match)
    #根据逗号将建表语句分组保存到列表中
    li=match.split(',')
    print(li,'\n')
    #用于存储数据字典的数据的字典类型列表
    data=[]
    for l in li:
        #将根据逗号分组保存的建表语句再分组，为了能将值填入数据字典中，比如要筛选出外键填入数据字典。连续的字母、数字、括号保留为一组，比如"aa_a varchar(10)"会被分为"aa_a"和"varchar(10)"，会被分别保存到列表ll里面
        ll=re.findall('[^ ]+',l)
        print('ll:',ll)
        #不区分大小写，判断ll列表里面的组是不是primary的主键关键词，如果是，则存入数据字典中
        if 'PRIMARY'.lower() in [x.lower() for x in ll]:
            data.append({'字段名称':ll[0],'字段类型':ll[1],'是否主键':'是'})
            if 'comment'.lower() in [x.lower() for x in ll]:
                for d in data:
                    if d['字段名称'] in ll[0]:
                        data[data.index(d)]['字段说明']=re.sub('\'','',ll[ll.index('comment')+1])
        #如果ll单词表没有primary单词,那么再判断它有没有references单词，这里必定处理外键ll。因为语句通常是外键作为约束条件放在后头，所以默认已经处理过这个键，这个外键已经在数据字典中，只是没有被识别，则找到被记录的这个外键，再给它添上外键消息
        elif 'KEY'.lower() in [x.lower() for x in ll]:
            for d in data:
                if (d['字段名称'] in ll[ll.index('key')+1]) and ('是否主键' not in d):
                    data[data.index(d)]['外键']=ll[ll.index('references')+1]+ll[ll.index('references')+2]
        #主键必然处理过，正常地存储剩下来的字段，后面遇到外键约束再设置一下外键消息
        else:
            data.append({'字段名称':ll[0],'字段类型':ll[1]})
            if 'comment'.lower() in [x.lower() for x in ll]:
                for d in data:
                    if (d['字段名称'] in ll[0]) and ('是否主键' not in d):
                        data[data.index(d)]['字段说明']=re.sub('\'','',ll[ll.index('comment')+1])
    print('\n',data)

    # 将数据写入 CSV 文件
    with open(csv_file, 'w', newline='') as file:
        fieldnames = ['字段名称', '字段类型', '是否主键', '外键','字段说明']
        writer = csv.DictWriter(file, fieldnames=fieldnames)
        writer.writeheader()
        if flag==1:
            writer.writerows([{'字段名称': t_name, '字段类型': '', '是否主键': '', '字段说明': ''}])
        writer.writerows(data)
    return data

def createInAll(target_path):
    # 指定要合并CSV文件的目录
    directory = target_path
    # 指定输出的Word文档名称
    output_docx = target_path+'000output.docx'
    # 创建一个新的Word文档
    doc = Document()
    # 遍历目录中的所有文件
    for filename in os.listdir(directory):
        # 检查文件是否是CSV文件
        if filename.endswith('.csv'):
            # 拼接文件完整路径
            file_path = os.path.join(directory, filename)
            # 读取CSV文件内容
            if file_path:
                print("========",file_path)
                df = pd.read_csv(file_path,encoding='gbk')
                # 将表格添加到Word文档中
                doc.add_paragraph(f'\n{df.iloc[0,0]}')  # 添加标题
                table=doc.add_table(df.shape[0],df.shape[1])
                for i in range(df.shape[0]):
                    for j in range(df.shape[1]):
                        cell=table.cell(i,j)
                        if i==0:
                            # 添加表头
                            cell.text=str(df.columns[j])
                        elif str(df.iloc[i,j])!='nan':
                            cell.text=str(df.iloc[i,j])
    # 保存Word文档
    doc.save(output_docx)
    print(f'所有CSV表格已插入到 {output_docx} 中。')

def run_f(sql_create,csv_file='./csv/'):
    if not os.path.exists(csv_file):
        os.mkdir(csv_file)
    match=sql_create.split('\n\n')
    for m in match:
        if 'create' in m:
            export_table_info(m,csv_file,1)
    createInAll(csv_file)
    for m in match:
        if 'create' in m:
            export_table_info(m,csv_file)





# 建表语句，要求主键约束在声明字段的时候已经创建，外键约束必须独立放在字段声明之后，外键声明的key单词与括号必须空格，具体规范如实例。局限性很大，只能针对某个数据库编辑器，当前版本并没有适配哪一种数据库编辑器，自行修改逻辑代码，应该没有太大难度
table_create_sql = """create table admin_t
(
    id         int         not null comment '主键'
        primary key,
    admin_name varchar(20) null comment '管理员名称',
    password   varchar(20) null comment '密码'
)
    comment '管理员表';

create table history_t
(
    id              int          not null comment '主键'
        primary key,
    school_name     varchar(200) null comment '高校名称',
    major           varchar(200) null comment '专业',
    batch           varchar(10)  null comment '批次',
    province        varchar(200) null comment '省市',
    year            varchar(5)   null comment '年份',
    top_score       int          null comment '最高分数',
    lowest_score    int          null comment '最低分数',
    subject_type    varchar(3)   null comment '文理科',
    admitted_number int          null comment '录取人数',
    reviewer        varchar(20)  null comment '复查人'
)
    comment '历年录取信息';

create table permission_t
(
    id              int          not null comment '主键'
        primary key,
    permission_name varchar(200) null comment '权限名称'
)
    comment '权限表';

create table role_t
(
    id        int         not null comment '主键'
        primary key,
    role_name varchar(20) null comment '角色名称'
)
    comment '角色表';

create table school_t
(
    id          int          not null comment '主键'
        primary key,
    school_name varchar(100) null comment '学校名称',
    phone       varchar(20)  null comment '联系方式',
    email       varchar(100) null comment '电子邮件',
    logo        varchar(200) null comment '图标'
)
    comment '学校信息表';

create table student_t
(
    id           int          not null comment '主键'
        primary key,
    student_name varchar(20)  null comment '学生名称',
    age          int          null comment '年龄',
    mayor        varchar(100) null comment '专业',
    school       varchar(200) null comment '所属学校',
    degree       varchar(200) null comment '学历',
    sex          varchar(3)   null comment '性别',
    province     varchar(200) null comment '所属省份',
    identity     varchar(30)  null comment '身份证号',
    phone        varchar(30)  null comment '电话号码'
)
    comment '学生信息表';

create table admission_t
(
    id         int      not null comment '主键'
        primary key,
    student_id int      null comment '学生信息',
    date       datetime null comment '创建时间',
    constraint admission_t_student_t_id_fk
        foreign key (student_id) references student_t (id)
)
    comment '录取通知书';

create table applications_t
(
    id          int         not null comment '主键'
        primary key,
    student_id  int         null comment '学生信息',
    school_id   int         null comment '目标高校',
    create_date datetime    null comment '创建时间',
    batch       varchar(10) null comment '批次',
    constraint applications_t_school_t_id_fk
        foreign key (school_id) references school_t (id),
    constraint applications_t_student_t_id_fk
        foreign key (student_id) references student_t (id)
)
    comment '填报志愿';

create table user_t
(
    id          int          not null comment '主键'
        primary key,
    avatar      varchar(200) null comment '头像',
    phone       varchar(30)  null comment '联系电话',
    email       varchar(30)  null comment '电子邮件',
    username    varchar(20)  null comment '用户名称',
    password    varchar(10)  null comment '密码',
    create_date datetime     null comment '创建日期',
    create_by   int          null comment '创建人'
)
    comment '用户表';

create table black_t
(
    id          int      not null comment '主键'
        primary key,
    user_id     int      null comment '用户信息',
    create_date datetime null comment '创建时间',
    create_by   int      null comment '操作者',
    constraint black_t_admin_t_id_fk
        foreign key (create_by) references admin_t (id),
    constraint black_t_user_t_id_fk
        foreign key (user_id) references user_t (id)
)
    comment '黑名单';

create table deleted_t
(
    id          int      not null comment '主键'
        primary key,
    user_id     int      null comment '用户信息',
    create_by   int      null comment '操作者',
    create_date datetime null comment '创建时间',
    constraint deleted_t_admin_t_id_fk
        foreign key (create_by) references admin_t (id),
    constraint deleted_t_user_t_id_fk
        foreign key (user_id) references user_t (id)
)
    comment '账号注销';

create table user_permission_t
(
    id            int      not null comment '主键'
        primary key,
    user_id       int      null comment '用户信息',
    permission_id int      null comment '权限信息',
    create_date   datetime null comment '创建时间',
    create_by     int      null comment '操作者',
    constraint user_permission_t_admin_t_id_fk
        foreign key (create_by) references admin_t (id),
    constraint user_permission_t_permission_t_id_fk
        foreign key (permission_id) references permission_t (id),
    constraint user_permission_t_user_t_id_fk
        foreign key (user_id) references user_t (id)
)
    comment '用户权限表';

create table user_role_t
(
    id          int      not null comment '主键'
        primary key,
    user_id     int      null comment '用户信息',
    role_id     int      null comment '角色信息',
    create_date datetime null comment '创建时间',
    create_by   int      null comment '操作者',
    constraint user_role_t_admin_t_id_fk
        foreign key (create_by) references admin_t (id),
    constraint user_role_t_role_t_id_fk
        foreign key (role_id) references role_t (id),
    constraint user_role_t_user_t_id_fk
        foreign key (user_id) references user_t (id)
)
    comment '用户角色表';


"""

# 导出数据字典到 CSV 文件
run_f(table_create_sql)